#ifndef SERVER_H
#define SERVER_H

#include <QObject>
#include <QDebug>
#include <QDateTime>
#include <QFileInfo>
#include <QUuid>
#include <QIcon>
#include <QHttpServer>
#include <QProtobufSerializer>

/********************************
 * 日志
 *******************************/
namespace ns_log
{
enum class LogLevel {
    Info,
    Debug,
    Warning,
    Error,
    Fatal
};


inline QDebug Log(LogLevel level, const QString &file, int line)
{

    QString levelStr;
    switch(level) {
    case LogLevel::Info:    levelStr = "INFO"; break;
    case LogLevel::Debug:   levelStr = "DEBUG"; break;
    case LogLevel::Warning: levelStr = "WARNING"; break;
    case LogLevel::Error:  levelStr = "ERROR"; break;
    case LogLevel::Fatal:  levelStr = "FATAL"; break;
    }

    QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");

    // 简化文件名显示（只显示最后一部分）
    QFileInfo fileinfo(file);
    QString simplifiedFile = fileinfo.fileName();

    // QString simplifiedFile = file.mid(file.lastIndexOf('\\') + 1);

    //qDebug默认会打印双引号，加上noquote就没有了
    return qDebug().noquote() <<
           QString("[%1][%2:%3][%4]").arg(levelStr,simplifiedFile,QString::number(line),timestamp);
}
}

// 使用宏定义简化调用
#define LOG_INFO    ns_log::Log(ns_log::LogLevel::Info,    __FILE__, __LINE__)
#define LOG_DEBUG   ns_log::Log(ns_log::LogLevel::Debug,   __FILE__, __LINE__)
#define LOG_WARNING ns_log::Log(ns_log::LogLevel::Warning, __FILE__, __LINE__)
#define LOG_ERROR   ns_log::Log(ns_log::LogLevel::Error,   __FILE__, __LINE__)
#define LOG_FATAL   ns_log::Log(ns_log::LogLevel::Fatal,   __FILE__, __LINE__)


/********************************
 * 工具
 *******************************/
namespace tool{
// 通过这个方法生成唯一的 messageId
static inline QString makeId(const QString& type)
{
    //原本生成的UUID："{52fdaef1-451e-4c01-8a29-90b307f48ab9}"，我们只取后12位，前面再加上是什么类型的uuid
    return type + QUuid::createUuid().toString().sliced(25,12);
}

// 通过这个函数得到 秒级 的时间
static inline int64_t getTime()
{
    return QDateTime::currentSecsSinceEpoch();
}

// 要求函数的定义如果写在 .h 中, 必须加 static 或者 inline (当然两个都加也可以), 避免链接阶段出现 "函数重定义" 的问题.
static inline QString formatTime(int64_t timestamp)
{
    // 先把时间戳, 转换成 QDateTime 对象
    QDateTime datetime = QDateTime::fromSecsSinceEpoch(timestamp);
    // 把 QDateTime 对象转成 "格式化时间"
    return datetime.toString("MM-dd HH:mm:ss");
}

// 根据 QByteArray, 转成 QIcon
static inline QIcon makeIcon(const QByteArray& bytearray)
{
    QPixmap pixmap;
    pixmap.loadFromData(bytearray);
    QIcon icon(pixmap);
    return icon;
}

// 读写文件操作.
// 从指定文件中, 读取所有的二进制内容. 得到一个 QByteArray
static inline QByteArray loadFileToByteArray(const QString& path)
{
    QFile file(path);
    bool ok = file.open(QFile::ReadOnly);
    if(!ok)
    {
        LOG_ERROR << "文件打开失败！";
        return QByteArray();
    }
    QByteArray content = file.readAll();
    file.close();
    return content;
}

// 把 QByteArray 中的内容, 写入到某个指定文件里
static inline void writeContentToFile(const QString& path,const QByteArray& content)
{
    QFile file(path);
    bool ok = file.open(QFile::WriteOnly);
    if(!ok)
    {
        LOG_ERROR << "文件打开失败！";
        return;
    }
    file.write(content);
    file.flush();
    file.close();
}
}   // end tool

namespace server
{
/******************************
 *  HttpServer
 *****************************/

class HttpServer : public QObject
{
    Q_OBJECT
public:
    static HttpServer* getInstance();
private:
    HttpServer(){};
    HttpServer(const HttpServer&) = delete;
    HttpServer& operator=(const HttpServer&) = delete;
    static HttpServer* instance;

    QHttpServer httpServer;
    QProtobufSerializer serializer;

public:
    bool init();
signals:

};

}   //end server

#endif // SERVER_H
